package com.lk.recvice.server.netty;


import com.lk.base.config.PropConf;
import com.lk.base.exception.CommonException;
import com.lk.recvice.server.MyServerSocket;
import com.lk.recvice.server.MySocketChannel;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;

@Component(value = "MyServerKeepalive")
@Order(2)
public class MyServer implements ApplicationRunner{

	static Logger logger = LoggerFactory.getLogger(MyServer.class);


	private static Channel serverChannel;

    /** 关闭当前server */
    public static void closeServer() {
        if (serverChannel != null) {
        	logger.info("close server");
            serverChannel.close();
            serverChannel = null;
        }
    }


	public void  startServer() throws Exception{
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup wokerGroup = new NioEventLoopGroup(4);

        try{

            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //在服务器端的handler()方法表示对bossGroup起作用，而childHandler表示对wokerGroup起作用
            serverBootstrap.group(bossGroup,wokerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128)
					//有数据立即发送
					.option(ChannelOption.TCP_NODELAY, true)
					//保持连接
					.childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new MyServerInitializer());

            ChannelFuture channelFuture = serverBootstrap.bind(PropConf.getIntValueByKey("keepalive.port")).sync();
            channelFuture.channel().closeFuture().sync();

            System.out.println(PropConf.getIntValueByKey("keepalive.port") + "  启动成功");
        }finally {
            bossGroup.shutdownGracefully();
            wokerGroup.shutdownGracefully();
        }
    }


	public static boolean pushWithSnId(String snId,String data) throws Exception {

		Map<String, MySocketChannel> maps = MyServerSocket.socketChannel_keepalive;
		Collection<MySocketChannel> values = maps.values();
		for (MySocketChannel mySocketChannel : values) {
			if(mySocketChannel.getSnId()!=null){
				if(mySocketChannel.getSnId().equals(snId)) {
					return push(mySocketChannel.getSocketChannel().id().toString(), data);
				}
			}

		}
		return false;
	}

	public static boolean push(String id,String data) throws Exception{
		SocketChannel context = MyServerSocket.socketChannel_keepalive.get(id).getSocketChannel();
		if(context == null) {
			throw new CommonException("ID为" + id + "的连接设备不存在！");
		}
		try {
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			throw new CommonException("ID为" + id + "的连接设备下发数据失败");
		}
	}


	public static void main(String[] args) {
		MyServer server = new MyServer();
		try {
			server.startServer();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}



	@Override
	public void run(ApplicationArguments args) throws Exception {
//		this.closeServer();
		new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					startServer();
				} catch (Exception e) {
					e.printStackTrace();
				}

			}
		}).start();
	}

}
